from PIL import Image


def bilinear_image_zoom(image_path, output_path, scale_factor):
    """
    使用双线性插值法对输入图像进行放大操作。

    参数:
    image_path (str): 输入图像的文件路径。
    output_path (str): 输出放大后图像的文件路径。
    scale_factor (float): 放大倍数，例如2表示将图像的长和宽都放大2倍。
    """
    # 打开原始图像
    image = Image.open(image_path)
    width, height = image.size
    new_width = int(width * scale_factor)
    new_height = int(height * scale_factor)
    # 创建新的空白图像，尺寸为放大后的尺寸，模式与原图像相同
    new_image = Image.new(image.mode, (new_width, new_height))

    # 双线性插值法实现图像放大
    for y in range(new_height):
        for x in range(new_width):
            # 计算在原图像中的对应坐标（浮点数坐标）
            old_x = x / scale_factor
            old_y = y / scale_factor
            # 获取原图像中对应坐标的整数部分和小数部分
            x1 = int(old_x)
            y1 = int(old_y)
            x2 = min(x1 + 1, width - 1)
            y2 = min(y1 + 1, height - 1)
            dx = old_x - x1
            dy = old_y - y1

            # 获取原图像中四个相邻像素点的像素值
            pixel_11 = image.getpixel((x1, y1))
            pixel_12 = image.getpixel((x1, y2))
            pixel_21 = image.getpixel((x2, y1))
            pixel_22 = image.getpixel((x2, y2))

            # 对红色通道进行双线性插值计算
            red_11, green_11, blue_11 = pixel_11
            red_12, green_12, blue_12 = pixel_12
            red_21, green_21, blue_21 = pixel_21
            red_22, green_22, blue_22 = pixel_22

            red_result = (1 - dx) * (1 - dy) * red_11 + dx * (1 - dy) * red_21 + (1 - dx) * dy * red_12 + dx * dy * red_22
            # 对绿色通道进行双线性插值计算
            green_result = (1 - dx) * (1 - dy) * green_11 + dx * (1 - dy) * green_21 + (1 - dx) * dy * green_12 + dx * dy * green_22
            # 对蓝色通道进行双线性插值计算
            blue_result = (1 - dx) * (1 - dy) * blue_11 + dx * (1 - dy) * blue_21 + (1 - dx) * dy * blue_12 + dx * dy * blue_22

            # 将插值计算后的像素值设置到新图像对应坐标位置
            new_image.putpixel((x, y), (int(red_result), int(green_result), int(blue_result)))

    # 保存放大后的图像
    new_image.save(output_path)
    return new_image

image_path = "test.jpg"
output_path = "zoomed_test.jpg"
scale_factor = 2
bilinear_image_zoom(image_path, output_path, scale_factor)